package com.yingxin.yxerp.module.report.task.common.util;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.yingxin.yx.framework.commons.enums.task.DynamicTaskLogCategoryEnum;
import com.yingxin.yxerp.module.report.task.entity.DynamicTask;
import com.yingxin.yxerp.module.report.task.mapper.DynamicTaskMapper;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;

/**
 * quartz工具类
 * @author yuebao
 * @date 2023-11-25
 */

@Slf4j
@Component
public class QuartzManager {

    /**
     * 参数传递key
     */
    public static final String PARAM_KEY = "task_name";

    /**
     * 程序调度器
     */
    @Autowired
    private Scheduler scheduler;

    @Resource
    private DynamicTaskMapper dynamicTaskMapper;

    /**
     * 系统启动执行
     */
    @PostConstruct
    public void init() {
        List<DynamicTask> list = dynamicTaskMapper.selectList(null);
        if (CollectionUtil.isNotEmpty(list)) {
            for (DynamicTask item : list) {
                try {
                    add(
                        item.getId(),
                        item.getCron(),
                        JSON.toJSONString( item.getTaskName() ),
                        item.getStatus(),
                        item.getClassName()
                    );
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }
        }
    }

    /**
     * 添加定时任务
     */
    public void add( String id, String cronExpression, String param, Boolean status, String className ) {
        try {
            // 构建job信息
            JobDetail jobDetail = JobBuilder.newJob( getClass( className ).getClass() ).
                    withIdentity( getKey( id ) ).usingJobData( PARAM_KEY, param ).build();
            // 表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            // 按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getKey(id)).withSchedule(scheduleBuilder).build();
            // 创建定时任务
            scheduler.scheduleJob(jobDetail, trigger);

            // scheduler.checkExists( trigger.getJobKey() );
            // 停止
            if (!status) {
                stop(id);
            }
        } catch (Exception e) {
            log.error("添加定时任务失败：{}", e.getMessage());
        }
    }

    /**
     * 编辑定时任务
     */
    public void update( String id, String cronExpression, String param, Boolean status, String className) {
        try {
            // 判断是否存在，存在先删除
            if (scheduler.checkExists(JobKey.jobKey(getKey(id)))) {
                scheduler.deleteJob(JobKey.jobKey(getKey(id)));
            }
            // 再创建
            add( id, cronExpression, param, status, className );
        } catch (Exception e) {
            log.error("修改定时任务失败：{}", e.getMessage());
        }
    }

    /**
     * 检测任务是否存在
     */
    public boolean myCheckExists( String id ){
        try {
            return scheduler.checkExists( JobKey.jobKey( getKey( id ) ) );
        } catch (Exception e) {
            log.error("检测定时任务失败：{}", e.getMessage());
        }
        return false;
    }

    /**
     * 暂停任务
     */
    public void stop(String id) {
        try {
            scheduler.pauseJob( JobKey.jobKey( getKey( id ) ) );
        } catch (SchedulerException e) {
            // 暂停定时任务失败
            log.error("暂停定时任务失败：{}", e.getMessage());
        }
    }

    /**
     * 恢复任务
     */
    public void start( String id ) {
        try {
            scheduler.resumeJob( JobKey.jobKey( getKey( id ) ) );
        } catch (SchedulerException e) {
            // 暂停定时任务失败
            log.error("启动定时任务失败：{}", e.getMessage());
        }
    }

    /**
     * 立即执行一次
     */
    public void run( String id ) {
        try {
            JobDataMap jobDataMap = new JobDataMap();
            jobDataMap.put( "category", DynamicTaskLogCategoryEnum.MANUAL.getType() );
            scheduler.triggerJob( JobKey.jobKey( getKey( id ) ), jobDataMap );
        } catch (SchedulerException e) {
            // 暂停定时任务失败
            log.error("执行定时任务失败：{}", e.getMessage());
        }
    }

    /**
     * 删除定时任务
     */
    public void delete( String id) {
        try {
            // 停止触发器
            scheduler.pauseTrigger( TriggerKey.triggerKey( getKey( id ) ) );
            // 移除触发器
            scheduler.unscheduleJob( TriggerKey.triggerKey( getKey( id ) ) );
            // 删除任务
            scheduler.deleteJob( JobKey.jobKey( getKey( id ) ) );
        } catch (Exception e) {
            log.error("删除定时任务失败：{}", e.getMessage());
        }
    }

    /**
     * 根据类名获取类
     */
    private Job getClass(String className) throws Exception {
        Class<?> class1 = Class.forName(className);
        return (Job) class1.newInstance();
    }

    /**
     * 拼接key
     * @return
     */
    public String getKey(String id) {
        return "task-" + id;
    }

}
